﻿// I commented out all the old file.
// If if doesn't work, then you can easily go back
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using UWBGL_WinForms_Lib1;
using UWBGL_XNA_Lib13;



namespace XNA_SceneNode
{
	public class Submarine : UWB_SceneNode // Submarine class is a scene-node
	{
		UWB_SceneNode lightBeam1, lightBeam2;

		//These are pointer to Nodes that we can use for movement & Colision
		private UWB_SceneNode SubBodyNode;
		private UWB_SceneNode WheelNode;
		private UWB_SceneNode ScopeNode;
		private UWB_SceneNode ArmNode;
		private UWB_SceneNode LittleArmNode;
		private UWB_SceneNode PincherTopNode;
		private UWB_SceneNode PincherBottomNode;

		// orient direction correctly
		private enum direction { left, right };
		private direction currentlyFacing = direction.right;

		private double jitterState = 0;
		private double swingState = 0;

		// constructor
		public Submarine(string arg)
			: base(arg)
		{			
			// centers sub's pivot in middle of whole object; set to 0 vector to cancel effect
			Vector3 correctionFactor = new Vector3(-6f, -2f, 0); 

			//Make a primitive list
			UWB_PrimitiveList SubBody = new UWB_PrimitiveList();

			// link primitive-list to current scene node
			setPrimitive(SubBody);

			//Make the front circle
			UWB_PrimitiveCircle Front = new UWB_PrimitiveCircle();
			Front.setCenter(new Vector3(10.0f, 2.0f, 0.0f) + correctionFactor);
			Front.setRadius(2.0f);
			Front.setFlatColor(new Color(255, 255, 00, 0));
			Front.setShadeMode(eShadeMode.smFlat);
			SubBody.append(Front);

			//Make the back of the sub
			UWB_PrimitiveCircle Back = new UWB_PrimitiveCircle();
			Back.setCenter(new Vector3(2.0f, 2.0f, 0.0f) + correctionFactor);
			Back.setRadius(2.0f);
			Back.setFlatColor(new Color(255, 255, 00, 0));
			Back.setShadeMode(eShadeMode.smFlat);
			SubBody.append(Back);

			//Make the square body
			UWB_PrimitiveRectangle Box = new UWB_PrimitiveRectangle();
			Box.setCorners(new Vector3(2.0f, 0.0f, 0.0f) + correctionFactor, new Vector3(10.0f, 4.0f, 0.0f) + correctionFactor);
			Box.setFlatColor(new Color(255, 255, 00));
			Box.setShadeMode(eShadeMode.smFlat);
			Box.enableTexturing(true);
			Box.setTextureFileName("Sub Body");
			SubBody.append(Box);

			// make the light beams
			lightBeam1 = new UWB_SceneNode();
			Triangle beam1 = new Triangle();
			beam1.radius = 20;
			beam1.center = new Vector3(5.9f, 0.5f, 0) + correctionFactor;
			beam1.setBaseWidth(4);
			beam1.setFlatColor(new Color(0.99f, 0.99f, 0.99f, 0f)); // lower color
			beam1.setShadingColor(new Color(0.9f, 0.9f, 0.9f, 0.9f)); // upper color
			beam1.enableBlending(true);
			lightBeam1.setPrimitive(beam1);

			lightBeam2 = new UWB_SceneNode();
			Triangle beam2 = new Triangle();
			beam2.radius = 20;
			beam2.center = new Vector3(6.1f, 0.5f, 0) + correctionFactor;
			beam2.setBaseWidth(4);
			beam2.setFlatColor(new Color(0.99f, 0.99f, 0.99f, 0f)); // lower color
			beam2.setShadingColor(new Color(0.9f, 0.9f, 0.9f, 0.9f)); // upper color
			beam2.enableBlending(true);
			lightBeam2.setPrimitive(beam2);

			//Make the neck
			UWB_PrimitiveRectangle Neck = new UWB_PrimitiveRectangle();
			Neck.setCorners(new Vector3(4.0f, 4.0f, 0.0f) + correctionFactor, new Vector3(8.0f, 8.0f, 0.0f) + correctionFactor);
			Neck.setFlatColor(new Color(255, 255, 00));
			Neck.setShadeMode(eShadeMode.smFlat);
			SubBody.append(Neck);


			//Make the Window
			UWB_PrimitiveCircle Window = new UWB_PrimitiveCircle();
			Window.setCenter(new Vector3(6.0f, 6.0f, 0.0f) + correctionFactor);
			Window.setRadius(1.0f);
			Window.setFlatColor(new Color(00, 255, 255, 0));
			Window.setShadeMode(eShadeMode.smFlat);
			SubBody.append(Window);

			//SubNode = Sub;
			SubBodyNode = this;


			//Make a scene node for our Wheel & hook up
			UWB_SceneNode Wheel = new UWB_SceneNode("Wheel");
			insertChildNode(Wheel);

			//Make a primitive list
			UWB_PrimitiveList WheelList = new UWB_PrimitiveList();

			//Make the Wheel star
			//UWB_PrimitiveStar WheelStar = new UWB_PrimitiveStar();
			CustomizedStar WheelStar = new CustomizedStar();
			WheelStar.edges = 20; // star edges
			WheelStar.innerRingSize = 0.8f; // how far the spikes extend
			WheelStar.setCenter(new Vector3(1.0f, 1.0f, 0.0f) + correctionFactor);
			WheelStar.setRadius(2.0f);
			WheelStar.setFlatColor(new Color(100, 100, 100, 90));
			WheelStar.setShadeMode(eShadeMode.smFlat);
			WheelList.append(WheelStar);
			Wheel.setPrimitive(WheelList);

			WheelNode = Wheel;

			UWB_XFormInfo Wheelxf = Wheel.getXFormInfo();
			Wheelxf.setRotationDegrees(0.0f);
			Wheelxf.setTranslation(new Vector3(0.0f, 0.0f, 0.0f));
			Wheelxf.setPivot(new Vector3(1.0f, 1.0f, 0.0f) + correctionFactor);
			Wheel.setXFormInfo(Wheelxf);

			///////////////////////////////////
			//Ok done making the body of the sub
			///////////////////////////////////

			//Let's make the Neck of the scope
			//Make a scene node for our ScopeNeck & hook up
			UWB_SceneNode ScopeNeck = new UWB_SceneNode("Scope Neck");
			insertChildNode(ScopeNeck);

			//Make a primitive list
			UWB_PrimitiveList ScopeList = new UWB_PrimitiveList();

			//Make the square ScopeNeck
			UWB_PrimitiveRectangle SNeck = new UWB_PrimitiveRectangle();
			SNeck.setCorners(new Vector3(5.0f, 8.0f, 0.0f) + correctionFactor, new Vector3(7.0f, 12.0f, 0.0f) + correctionFactor);
			SNeck.setFlatColor(new Color(00, 00, 00));
			SNeck.setShadeMode(eShadeMode.smFlat);
			ScopeList.append(SNeck);

			ScopeNeck.setPrimitive(ScopeList);

			UWB_XFormInfo SNxf = ScopeNeck.getXFormInfo();
			SNxf.setRotationDegrees(0.0f);
			SNxf.setTranslation(new Vector3(0.0f, 0.0f, 0.0f));
			SNxf.setPivot(new Vector3(6.0f, 8.0f, 0.0f));
			ScopeNeck.setXFormInfo(SNxf);

			//Now the actual Scope itself
			//Make a scene node for our Scope & hook up
			UWB_SceneNode Scope = new UWB_SceneNode("Scope");
			ScopeNeck.insertChildNode(Scope);

			//Make a primitive list
			UWB_PrimitiveList ScopeL = new UWB_PrimitiveList();

			//Make the square Scope
			UWB_PrimitiveRectangle ScopeRec = new UWB_PrimitiveRectangle();
			ScopeRec.setCorners(new Vector3(7.0f, 10.0f, 0.0f) + correctionFactor, new Vector3(11.0f, 12.0f, 0.0f) + correctionFactor);
			ScopeRec.setFlatColor(new Color(00, 00, 00));
			ScopeRec.setShadeMode(eShadeMode.smFlat);
			ScopeL.append(ScopeRec);

			ScopeNode = Scope;

			//Then we set the primitive
			Scope.setPrimitive(ScopeL);
			//ScopeNetHolder = Scope;
			UWB_XFormInfo Sxf = Scope.getXFormInfo();
			Sxf.setRotationDegrees(0.0f);
			Sxf.setTranslation(new Vector3(0.0f, 0.0f, 0.0f));
			Sxf.setPivot(new Vector3(7.0f, 11.0f, 0.0f) + correctionFactor);
			Scope.setXFormInfo(Sxf);

			/////////////////////////////////
			//Now let's make the Grabbers & Net
			/////////////////////////////////

			// We need to hook this up to the sub body
			//Make a scene node for our ScopeNeck & hook up
			UWB_SceneNode Arm = new UWB_SceneNode("Arm");
			insertChildNode(Arm);

			//Make a primitive list
			UWB_PrimitiveList ArmList = new UWB_PrimitiveList();

			//Make the square of Arm
			UWB_PrimitiveRectangle ArmRec = new UWB_PrimitiveRectangle();
			ArmRec.setCorners(new Vector3(10.0f, 1.0f, 0.0f) + correctionFactor, new Vector3(16.0f, 3.0f, 0.0f) + correctionFactor);
			ArmRec.setFlatColor(new Color(00, 00, 00));
			ArmRec.setShadeMode(eShadeMode.smFlat);
			ArmList.append(ArmRec);
			Arm.setPrimitive(ArmList);

			UWB_XFormInfo Axf = Arm.getXFormInfo();
			Axf.setRotationDegrees(0.0f);
			Axf.setTranslation(new Vector3(0.0f, 0.0f, 0.0f));
			Axf.setPivot(new Vector3(10.0f, 2.0f, 0.0f) + correctionFactor);
			//Axf.setScale(new Vector3(0.5f, 1.0f, 1.0f));
			Arm.setXFormInfo(Axf);

			ArmNode = Arm;

			// Arm 2
			//Make a scene node for our Arm2 & hook up
			UWB_SceneNode LittleArm = new UWB_SceneNode("Little Arm");
			Arm.insertChildNode(LittleArm);

			//Make a primitive list
			UWB_PrimitiveList Arm2List = new UWB_PrimitiveList();

			//Make the square Arm2
			UWB_PrimitiveRectangle Arm2Rec = new UWB_PrimitiveRectangle();
			Arm2Rec.setCorners(new Vector3(16.0f, 1.0f, 0.0f) + correctionFactor, new Vector3(20.0f, 3.0f, 0.0f) + correctionFactor);
			Arm2Rec.setFlatColor(new Color(00, 00, 00));
			Arm2Rec.setShadeMode(eShadeMode.smFlat);
			Arm2List.append(Arm2Rec);
			LittleArm.setPrimitive(Arm2List);

			//This is the Node to keep track of targets
			LittleArmNode = LittleArm;

			UWB_XFormInfo LAxf = LittleArm.getXFormInfo();
			LAxf.setRotationDegrees(0.0f);
			LAxf.setTranslation(new Vector3(0.0f, 0.0f, 0.0f));
			LAxf.setPivot(new Vector3(16.0f, 2.0f, 0.0f) + correctionFactor);
			// We'll shrink it down for now
			LAxf.setScale(new Vector3(1.0f, 1.0f, 0.2f));
			LittleArm.setXFormInfo(LAxf);


			// Arm Pincher Top
			//Make a scene node for our PincherTop & hook up
			UWB_SceneNode PincherTop = new UWB_SceneNode("Pincher Top");
			LittleArm.insertChildNode(PincherTop);

			//Make a primitive list for Pincher Top
			UWB_PrimitiveList PincherTopList = new UWB_PrimitiveList();

			//Make the square PincherTop
			UWB_PrimitiveRectangle PincherTopRec = new UWB_PrimitiveRectangle();
			PincherTopRec.setCorners(new Vector3(20.0f, 3.0f, 0.0f) + correctionFactor, new Vector3(22.0f, 4.0f, 0.0f) + correctionFactor);
			PincherTopRec.setFlatColor(new Color(00, 00, 00));
			PincherTopRec.setShadeMode(eShadeMode.smFlat);
			PincherTopList.append(PincherTopRec);
			PincherTop.setPrimitive(PincherTopList);

			//Hook up the Node
			PincherTopNode = PincherTop;

			//Set the piviot
			UWB_XFormInfo PTXF = PincherTop.getXFormInfo();
			PTXF.setRotationDegrees(0.0f);
			PTXF.setTranslation(new Vector3(0.0f, 0.0f, 0.0f));
			PTXF.setPivot(new Vector3(20.0f, 3.0f, 0.0f) + correctionFactor);
			PincherTop.setXFormInfo(PTXF);

			// Arm Pincher Bottom
			//Make a scene node for our PincherBottom & hook up
			UWB_SceneNode PincherBottom = new UWB_SceneNode("Pincher Bottom");
			LittleArm.insertChildNode(PincherBottom);

			//Make a primitive list for Pincher Bottom
			UWB_PrimitiveList PincherBottomList = new UWB_PrimitiveList();

			//Make the square PincherBottom
			UWB_PrimitiveRectangle PincherBottomRec = new UWB_PrimitiveRectangle();
			PincherBottomRec.setCorners(new Vector3(20.0f, 1.0f, 0.0f) + correctionFactor, new Vector3(22.0f, 0.0f, 0.0f) + correctionFactor);
			PincherBottomRec.setFlatColor(new Color(00, 00, 00));
			PincherBottomRec.setShadeMode(eShadeMode.smFlat);
			PincherBottomList.append(PincherBottomRec);
			PincherBottom.setPrimitive(PincherBottomList);

			//Hook up the bottom pincher Node
			PincherBottomNode = PincherBottom;

			//Set the piviot
			UWB_XFormInfo PBXF = PincherBottom.getXFormInfo();
			PBXF.setRotationDegrees(0.0f);
			PBXF.setTranslation(new Vector3(0.0f, 0.0f, 0.0f));
			PBXF.setPivot(new Vector3(20.0f, 1.0f, 0.0f) + correctionFactor);
			PincherBottom.setXFormInfo(PBXF);

			// We might need a xform info thing for our sub
			//This way we can positon, scale, etc. to make it look right.
			UWB_XFormInfo Subxf = getXFormInfo();
			Subxf.setRotationDegrees(0.0f);
			Subxf.setTranslation(new Vector3(0.0f, 0.0f, 0.0f));
			Subxf.setScale(new Vector3(0.3f, 0.3f, 0)); // scale submarine
			setXFormInfo(Subxf);
		}

		// roates wheel by specified amount in degrees
		public void rotateWheelDegree(float degreeToRotate)
		{
			UWB_XFormInfo wheelTransform = WheelNode.getXFormInfo();
			float rotation = wheelTransform.getRotationInDegrees();
			float newRotation = rotation + degreeToRotate;
			if (newRotation > 360) // periodic
				newRotation -= 360;
			wheelTransform.setRotationDegrees(newRotation);
			WheelNode.setXFormInfo(wheelTransform);
		}

		// flips submarine sideways according to velocity change in x-direction
		public void flipVelocity()
		{
			if (mVelocity.X > 0 && (currentlyFacing == direction.left)) // mismatch
			{
				UWB_XFormInfo submarineTransform = getXFormInfo();
				Vector3 origScale = submarineTransform.getScale();
				Vector3 newScale = origScale * (new Vector3(-1, 1, 0)); // flips x vertices
				submarineTransform.setScale(newScale);
				setXFormInfo(submarineTransform);

				currentlyFacing = direction.right; // set new dir
			}

			if (mVelocity.X < 0 && (currentlyFacing == direction.right)) // mismatch
			{
				UWB_XFormInfo submarineTransform = getXFormInfo();
				Vector3 origScale = submarineTransform.getScale();
				Vector3 newScale = origScale * (new Vector3(-1, 1, 0)); // flips x vertices
				submarineTransform.setScale(newScale);
				setXFormInfo(submarineTransform);

				currentlyFacing = direction.left; // set new dir
			}
		}

		// slightly move submarine left/right or up/down to simulate ocean current
		public void bobbingSubmarine()
		{
			// control variables
			float amplitude = 0.03f;
			jitterState += 0.08; // period of the function

			float jitterDelta = (float)Math.Sin(jitterState);
			float newY = mXFormInfo.getTranslation().Y + amplitude * jitterDelta;
			UWB_XFormInfo jitteredTransform = getXFormInfo();
			Vector3 oldTranslation = jitteredTransform.getTranslation();
			jitteredTransform.setTranslation(new Vector3(oldTranslation.X, newY, 0f));
			setXFormInfo(jitteredTransform);
		}

		private void swingLightBeams(UWB_SceneNode beam)
		{
			// control variables
			float amplitude = -0.4f;
			swingState += 0.01; // period of the function

			float swingDelta = (float)Math.Sin(swingState);
			float newRotation = beam.getXFormInfo().getRotationInDegrees() + amplitude * swingDelta;
			if (newRotation > 360) // periodic
				newRotation -= 360;

			UWB_XFormInfo newXF = beam.getXFormInfo();
			newXF.setRotationDegrees(newRotation);
			beam.setXFormInfo(newXF);
		}
		private void swingLightBeams1(UWB_SceneNode beam)
		{
			// control variables
			float amplitude = 0.4f;
			swingState += 0.01; // period of the function

			float swingDelta = (float)Math.Sin(swingState);
			float newRotation = beam.getXFormInfo().getRotationInDegrees() + amplitude * swingDelta;
			if (newRotation > 360) // periodic
				newRotation -= 360;

			UWB_XFormInfo newXF = beam.getXFormInfo();
			newXF.setRotationDegrees(newRotation);
			beam.setXFormInfo(newXF);
		}

		// draw, customized
		public new void draw(eLevelofDetail lod, UWB_DrawHelper drawHelper)
		{
			drawHelper.pushModelTransform();
			mXFormInfo.setupModelStack(drawHelper);

			if (mPrimitive != null)
			{
				mPrimitive.draw(lod, drawHelper);
			}

			int count = mChildNodes.count();
			for (int i = 0; i < count; i++)
			{
				mChildNodes.getItem(i).draw(lod, drawHelper);
			}

			lightBeam1.draw(lod, drawHelper);// draws light beams
			swingLightBeams(lightBeam1);
			lightBeam2.draw(lod, drawHelper);
			swingLightBeams1(lightBeam2);
			

			if (mPivotVisible)
			{
				mXFormInfo.drawPivot(drawHelper, 0.2f);
			}
			drawHelper.popModelTransform();
		}
		#region get and sets
		// "virtual" center as viewed from outside of this class
		public Vector3 Center
		{
			get { return getXFormInfo().getTranslation(); }
			set
			{
				if (value.X > 0 && value.Y > 0) // X & Y are world coordinates, always positive
				{
					mXFormInfo.setTranslation(value);
				}
			}
		}

		public UWB_SceneNode getArmNode()
		{
			return ArmNode;
		}
		public UWB_SceneNode getSubBodyNode()
		{
			return SubBodyNode;
		}
		public UWB_SceneNode getScopeNode()
		{
			return ScopeNode;
		}
		public UWB_SceneNode getWheelNode()
		{
			return WheelNode;
		}
		public UWB_SceneNode getLittleArmNode()
		{
			return LittleArmNode;
		}
		public UWB_SceneNode getPincherTopNode()
		{
			return PincherTopNode;
		}
		public UWB_SceneNode getPincherBottomNode()
		{
			return PincherBottomNode;
		}
		#endregion
	}
}